package com.itheima.spider;

import com.alibaba.fastjson2.JSON;
import com.gargoylesoftware.htmlunit.*;

import com.itheima.config.WebClientS;
import com.itheima.myenum.LinkTypeEnum;
import com.itheima.myenum.SpiderStatus;
import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecutor;
import org.apache.commons.exec.PumpStreamHandler;
import org.apache.commons.io.IOUtils;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class BilibiliSpider  {
     public WebClient webClient;
    //json数据
    private String content;

    public Integer spiderStatus;

//    public Boolean SpiderBatch=false;
    public BilibiliSpider(URL url, HttpMethod httpMethod) throws IOException {
        webClient= WebClientS.getNewWebClient();
        spiderStatus = SpiderPage(url, httpMethod);
    }
    // 爬取js脚本,提取json数据
    private Integer SpiderPage(URL url, HttpMethod httpMethod) throws IOException {
        WebRequest webRequest = new WebRequest(url, httpMethod); // 创建请求对象，设置请求的URL和HTTP方法

        Page page = webClient.getPage(webRequest); // 发起请求，获取页面

        WebResponse webResponse = page.getWebResponse();
        String contentAsString = webResponse.getContentAsString();
        //url 有误 请求失败
        if (webResponse.getStatusCode() != 200) {
            System.out.println("请求失败，状态码：" + webResponse.getStatusCode());
            return SpiderStatus.REJECTED.getCode();
        }
         // 创建 正则表达式对象，匹配包含window.__playinfo__的script标签及其内容
        Pattern compile = Pattern.compile("<script>window.__playinfo__\\s*=\\s*(.*?)</script>");
        Matcher matcher = compile.matcher(contentAsString);
        String group = null;
        if (matcher.find()) {
            group = matcher.group(1);
            this.content = group;
            return  SpiderStatus.SUCCESS.getCode();
        }else {
            System.out.println("未找到匹配的脚本");
            return SpiderStatus.NO_MATCH.getCode();
        }
    }
    //提取链接
    private String ExtractLink(String content, LinkTypeEnum linkType){
        return  JSON.parseObject(content).getJSONObject("data").getJSONObject("dash").getJSONArray(linkType.getType()).getJSONObject(0).getString("baseUrl");
    }
    //下载视频 (返回 文件名)
    private String Download_(LinkTypeEnum linkTypeEnum) throws IOException {

        String Link = ExtractLink(content, linkTypeEnum);
        WebRequest webRequest=new WebRequest(new URL(Link));
        Page page = webClient.getPage(webRequest);
        InputStream contentAsStream = page.getWebResponse().getContentAsStream();
        String id = UUID.randomUUID().toString(); //uuid的格式 一般为 8-4-4-4-12

        if (linkTypeEnum.equals(LinkTypeEnum.VIDEO)) {
            IOUtils.copy(contentAsStream, Files.newOutputStream(Paths.get(id+".mp4")));
            return id+".mp4";
        }else {
            IOUtils.copy(contentAsStream, Files.newOutputStream(Paths.get(id+".mp3")));
            return id+".mp3";
        }

    }
    // 合并视频和音频
    public void Download_Merge_VideoAndAudio(String outputFile) throws IOException {
        String videoFile = Download_(LinkTypeEnum.VIDEO); // 临时文件
        String audioFile = Download_(LinkTypeEnum.AUDIO); // 临时文件
        //判断outPutFile 是不是一条目录路径
        if (Files.isDirectory(Paths.get(outputFile))){
            String fileName = UUID.randomUUID().toString();
            outputFile= outputFile+"\\"+fileName+".mp4";
        }
        // 创建合并音视频的命令
        String[] cmd = {
                "ffmpeg",
                "-i", videoFile,    // 输入视频文件
                "-i", audioFile,    // 输入音频文件
                "-c:v", "libx264",     // copy保持视频编码格式不变 但是javafx只支持h264 所以这里改成libx264！
                "-c:a", "aac",      // 使用 AAC 音频编码
                "-strict", "experimental", // 启用实验性的 AAC 编码
                "-map", "0:v:0",    // 映射视频流
                "-map", "1:a:0",    // 映射音频流
                "-shortest",        // 使输出文件的时长与较短的流一致
                outputFile          // 输出文件 就是我们输入的savepath
        };
        // 创建CommandLine对象，并执行ffmpeg命令
        CommandLine commandLine = CommandLine.parse(String.join(" ", cmd));
        DefaultExecutor defaultExecutor = new DefaultExecutor();
        PumpStreamHandler pumpStreamHandler = new PumpStreamHandler(System.out, System.err); // 将ffmpeg的输出重定向到控制台

        defaultExecutor.setStreamHandler(pumpStreamHandler); // 设置流处理器
        try {
            int exitValue = defaultExecutor.execute(commandLine);
            System.out.println("ffmpeg执行完成，退出码：" + exitValue);
        }catch (Exception e){
            e.printStackTrace();
        }
        // 删除临时文件
        Files.deleteIfExists(Paths.get(videoFile));
        Files.deleteIfExists(Paths.get(audioFile));
        System.out.println("临时文件已删除。");
    }
    public void onlyForAu (String outPutFile) throws IOException {
        String Link = ExtractLink(content, LinkTypeEnum.AUDIO);
        WebRequest webRequest=new WebRequest(new URL(Link));
        Page page = webClient.getPage(webRequest);
        InputStream contentAsStream = page.getWebResponse().getContentAsStream();
        //判断outPutFile 是不是一条目录路径
        if (Files.isDirectory(Paths.get(outPutFile))){
            String fileName = UUID.randomUUID().toString();
            // 例如 ：D:\我的音乐\周杰伦
            outPutFile= outPutFile+"\\"+fileName+".mp3";
            // 下载音频文件
            IOUtils.copy(contentAsStream, Files.newOutputStream(Paths.get(outPutFile)));
        }else {
            // 下载音频文件 路径例子：D:\我的音乐\周杰伦\52552.mp3
            IOUtils.copy(contentAsStream, Files.newOutputStream(Paths.get(outPutFile)));
        }
    }

}
